<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>OpenMesh: Read and write meshes from files</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
  $(document).ready(initResizable);
</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="logo_align.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="rwth_vci_rgb.jpg"/></td>
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname">OpenMesh
   </div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "search",false,'Search');
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
$(document).ready(function(){initNavTree('a04327.html','');});
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">Read and write meshes from files </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>This section explains the methods used to read a mesh from a file or write it to a file.</p>
<p>The corresponding functions are defined in the namespace OpenMesh::MeshIO. This section is divided into three steps. Step one will give a short example on how to use the OpenMesh IOManager, step two will give some background information on how IOManager works and finally step three will show you how to add your own modules to IOManager.</p>
<p>A tutorial with more information regarding file IO can be found here: <a class="el" href="a04344.html">Using IO::Options</a></p>
<h1><a class="anchor" id="mesh_io_quick"></a>
Step 1 - IOManager quick start</h1>
<p>For a quick start you can copy the following code directly to your project.</p>
<dl class="section note"><dt>Note</dt><dd><ul>
<li>
If you link statically against <a class="el" href="a01233.html" title="Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...">OpenMesh</a>, you have to add the define OM_STATIC_BUILD to your application. This will ensure that readers and writers get initialized correctly. </li>
<li>
IOManager uses the filename extension to determine which reader/writer to use. I.e. if passing "inputmesh.obj" as filename parameter, the OBJ-File reader/writer will be used to parse/write the file. </li>
</ul>
</dd></dl>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;OpenMesh/Core/IO/MeshIO.hh&gt;</span></div><div class="line"></div><div class="line">MyMesh mesh;</div><div class="line"></div><div class="line"><span class="keywordflow">if</span> (!<a class="code" href="a01236.html#ac417960ec28ffdd7e7003a2b1ebb2d1c">OpenMesh::IO::read_mesh</a>(mesh, <span class="stringliteral">&quot;some input file&quot;</span>)) </div><div class="line">{</div><div class="line">  std::cerr &lt;&lt; <span class="stringliteral">&quot;read error\n&quot;</span>;</div><div class="line">  exit(1);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">// do something with your mesh ...</span></div><div class="line"></div><div class="line"><span class="keywordflow">if</span> (!<a class="code" href="a01236.html#a18286a792ebf896872f5e26182fc5c7b">OpenMesh::IO::write_mesh</a>(mesh, <span class="stringliteral">&quot;some output file&quot;</span>)) </div><div class="line">{</div><div class="line">  std::cerr &lt;&lt; <span class="stringliteral">&quot;write error\n&quot;</span>;</div><div class="line">  exit(1);</div><div class="line">}</div></div><!-- fragment --><p><br />
<br />
</p>
<h1><a class="anchor" id="mesh_io_theory"></a>
Step 2 - The theory behind IOManager</h1>
<p>Usually mesh reader and writer routines are written directly against the data structure and the respective file format they support. This approach has the main disadvantage that targeting a different data structure or adding another file format leads to duplication of code.</p>
<p>IOManager acts as an interface between persistent data on one side and an arbitrary data structure on the other side by means of reader/writer and importer/exporter modules. This is illustrated by the following diagramm :</p>
<div class="image">
<img src="iomanager.png" alt="iomanager.png"/>
</div>
<p><br />
</p>
<p>Persistent data of arbitrary format is first interpreted by a reader module. The data is then passed - by means of a specified interface - to an importer module for the target data structure. The process for writing data is analogous. The IOManager controls the entire process. Reader/Writer modules are invisible to the user. Importer/Exporter however have to be specified explicitely as they are specific to a data structure.</p>
<p>The complete separation of data structure and persistent data makes it especially easy to maintain existing code and to extend funtionality at both ends as will be shown in step three.</p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="a01236.html" title="This namespace contains functions for reading and writing polygonal meshes and a list of supported fi...">OpenMesh::IO</a>::<em>IOManager</em></dd></dl>
<p><br />
<br />
</p>
<h1><a class="anchor" id="mesh_io_extend"></a>
Step 3 - How to extend IOManager</h1>
<h2><a class="anchor" id="mesh_io_extend_fileformat"></a>
Adding support for a new file format</h2>
<p>Adding support for a new file format involves adding a reader and writer module. Reader modules are classes derived from <a class="el" href="a02033.html" title="Base class for reader modules. ">OpenMesh::IO::BaseReader</a>. The part of the interface that you usually have to define is shown below.</p>
<div class="fragment"><div class="line"><span class="keyword">class </span>BaseReader</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line"></div><div class="line">  <span class="keyword">virtual</span> std::string get_description() <span class="keyword">const</span> = 0;</div><div class="line">  <span class="keyword">virtual</span> std::string get_extensions() <span class="keyword">const</span> = 0;</div><div class="line">  <span class="keyword">virtual</span> std::string get_magic()<span class="keyword"> const </span>{ <span class="keywordflow">return</span> std::string(<span class="stringliteral">&quot;&quot;</span>); }</div><div class="line"></div><div class="line">  <span class="keyword">virtual</span> <span class="keywordtype">bool</span> read(std::istream&amp; _is, BaseImporter&amp; _bi) <span class="keyword">const</span> = 0;</div><div class="line">  <span class="keyword">virtual</span> <span class="keywordtype">bool</span> read(<span class="keyword">const</span> std::string&amp; _filename, BaseImporter&amp; _bi) <span class="keyword">const</span> = 0;</div><div class="line"></div><div class="line">  ...</div><div class="line">};</div></div><!-- fragment --><p>Based on the file extension or the header information the IOManager decides which reader module to use. The reader then parses the format and the information will be passed to the target data structure be means of a class derived from <a class="el" href="a02017.html" title="Base class for importer modules. ">OpenMesh::IO::BaseImporter</a>.</p>
<p>Writer modules are derived from <a class="el" href="a02081.html" title="Base class for all writer modules. ">OpenMesh::IO::BaseWriter</a> and work the same way as reader modules.</p>
<p><br />
</p>
<h2><a class="anchor" id="mesh_io_extend_datastruct"></a>
Adding support for a new data structure</h2>
<p>As we have already seen, Importers receive information from the reader modules. Reader modules pass information through a specified interface :</p>
<div class="fragment"><div class="line"><span class="keyword">class </span>BaseImporter</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line"></div><div class="line">  <span class="keyword">virtual</span> <span class="keywordtype">void</span> add_vertex  (<span class="keyword">const</span> <a class="code" href="a02001.html">OpenMesh::Vec3f</a>&amp;) {};</div><div class="line">  <span class="keyword">virtual</span> <span class="keywordtype">void</span> add_normal  (<span class="keyword">const</span> <a class="code" href="a02001.html">OpenMesh::Vec3f</a>&amp;) {};</div><div class="line">  <span class="keyword">virtual</span> <span class="keywordtype">void</span> add_texture (<span class="keyword">const</span> <a class="code" href="a02001.html">OpenMesh::Vec2f</a>&amp;) {};</div><div class="line">  <span class="keyword">virtual</span> <span class="keywordtype">void</span> add_face    (<span class="keyword">const</span> FaceType&amp;)        {};</div><div class="line">};</div></div><!-- fragment --><p>The Importer is then responsible for filling the target data structure. Exporting information from a data structure is a little bit more involved than importing data to it. The writer modules must be able to iterate over all vectors/texcoords/faces. Therefore an exporter has to provide these iterators :</p>
<div class="fragment"><div class="line"><span class="keyword">class </span>BaseExporter</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line"></div><div class="line">  <span class="keyword">virtual</span> <span class="keywordtype">void</span> update() = 0;</div><div class="line">  </div><div class="line">  <span class="keyword">virtual</span> PVertexIter const_vertices_begin()   = 0;</div><div class="line">  <span class="keyword">virtual</span> PVertexIter const_vertices_end()     = 0;</div><div class="line">  </div><div class="line">  <span class="keyword">virtual</span> PTexCoordIter const_texcoords_begin() = 0;</div><div class="line">  <span class="keyword">virtual</span> PTexCoordIter const_texcoords_end()   = 0;</div><div class="line"></div><div class="line">  <span class="keyword">virtual</span> PIdxFaceIter const_idx_faces_begin() = 0;</div><div class="line">  <span class="keyword">virtual</span> PIdxFaceIter const_idx_faces_end()   = 0;</div><div class="line"></div><div class="line">  <span class="keyword">virtual</span> PFaceIter const_set_faces_begin() = 0;</div><div class="line">  <span class="keyword">virtual</span> PFaceIter const_set_faces_end()   = 0;</div><div class="line"></div><div class="line">  <span class="keyword">virtual</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> n_faces()     = 0;</div><div class="line">  <span class="keyword">virtual</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> n_vertices()  = 0;</div><div class="line">  <span class="keyword">virtual</span> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> n_texcoords() = 0;</div><div class="line">};</div></div><!-- fragment --><p>There might be the need for the exporter to cache data from the structure it refers to. The update() function should be called at the beginning of each BaseWriter::save() method and it should make sure that cached information is up to date.</p>
<p>For further information you are encouraged to take a look at the modules provided by OpenMesh which can be found in the IO subdirectory. </p>
</div></div><!-- contents -->
</div><!-- doc-content -->
<hr>
<address>
<small>
<a href="http://www.rwth-graphics.de" style="text-decoration:none;">
</a>
Project <b>OpenMesh</b>, 
&copy;&nbsp; Computer Graphics Group, RWTH Aachen.
Documentation generated using 
<a class="el" href="http://www.doxygen.org/index.html">
<b>doxygen</b>
</a>.
</small>
</address>
</body>
</html>
